package cn.getech.data.metadata.service.impl;

import cn.getech.data.development.entity.ConfConnect;
import cn.getech.data.development.service.ConfConnectService;
import cn.getech.data.intelligence.common.exception.RRException;
import cn.getech.data.intelligence.common.utils.PageUtils;
import cn.getech.data.intelligence.common.utils.Query;
import cn.getech.data.metadata.constant.ConnectTypeEnum;
import cn.getech.data.metadata.constant.LogTypeEnum;
import cn.getech.data.metadata.controller.module.ModuleUtils;
import cn.getech.data.metadata.entity.CollectionSystemModuleEntity;
import cn.getech.data.metadata.entity.CollectionTaskScheduleConfigEntity;
import cn.getech.data.metadata.entity.meta.*;
import cn.getech.data.metadata.mapper.*;
import cn.getech.data.metadata.model.req.meta.CollectionTaskListReq;
import cn.getech.data.metadata.model.res.CollectionTaskLogDetail;
import cn.getech.data.metadata.model.res.CollectionTaskLogSource;
import cn.getech.data.metadata.model.res.log.FieldLog;
import cn.getech.data.metadata.model.res.log.TableLog;
import cn.getech.data.metadata.service.CollectionTaskLogService;
import cn.getech.data.metadata.service.CollectionTaskScheduleConfigService;
import cn.getech.data.metadata.utils.MapUtils;
import cn.getech.system.center.entity.SysRoleEntity;
import cn.getech.system.center.entity.SysUserEntity;
import cn.getech.system.center.mapper.SysUserMapper;
import cn.getech.system.center.service.SysRoleService;
import cn.getech.system.center.service.SysUserService;
import cn.getech.system.center.utils.ShiroUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class CollectionTaskLogServiceImpl extends
        ServiceImpl<CollectionTaskLogMapper, CollectionTaskLog>
        implements CollectionTaskLogService {
    @Autowired
    private CollectionTaskMapper collectionTaskMapper;
    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private CollectionTableFieldLogMapper collectionTableFieldLogMapper;
    @Autowired
    private CollectionTableInfoMapper collectionTableInfoMapper;
    @Autowired
    private CollectionTableFieldMapper collectionTableFieldMapper;
    @Autowired
    private CollectionSystemModuleMapper collectionSystemModuleMapper;
    @Autowired
    private CollectionRunLogMapper collectionRunLogMapper;
    @Autowired
    private CollectionTaskScheduleConfigService collectionTaskScheduleConfigService;
    @Autowired
    private ConfConnectService confConnectService;
    @Autowired
    private SysUserService sysUserService;
    @Autowired
    private SysRoleService sysRoleService;

    @Override
    public PageUtils selectListPage(CollectionTaskListReq req) {
        Map<String, Object> params = MapUtils.objectToMap(req);
        if (params != null) {
            Integer tenantId = ShiroUtils.getTenantId();
            Long userId = ShiroUtils.getUserId();
            params.put("tenantId", tenantId);
            params.put("userId", userId);
        }
        IPage<CollectionTaskLog> page = this.baseMapper.selectListPage(
                (Page<CollectionTaskLog>) new Query<CollectionTaskLog>()
                        .getPage(params), params);
        if (CollectionUtils.isNotEmpty(page.getRecords())) {
            Set<Long> userIds = page.getRecords().stream()
                    .filter(s -> s.getTaskRunLeader() != null)
                    .map(CollectionTaskLog::getTaskRunLeader).collect(Collectors.toSet());
            if (CollectionUtils.isNotEmpty(userIds)) {
                List<SysUserEntity> users = sysUserMapper.selectList(
                        new QueryWrapper<SysUserEntity>().in("user_id", userIds));
                Map<Long, String> userMap = Maps.newHashMap();
                for (SysUserEntity user : users) {
                    String name = user.getUsername();
                    userMap.put(user.getUserId(), name);
                }
                for (CollectionTaskLog record : page.getRecords()) {
                    record.setTaskRunLeaderName(userMap.get(record.getTaskRunLeader()));
                }
            }
        }
        return new PageUtils<>(page);
    }

    @Override
    public List<HashMap<String, Object>> selectVersionList(Long id) {
        CollectionTaskLog record = baseMapper.selectById(id);
        List<HashMap<String, Object>> res = Lists.newArrayList();
        List<CollectionTaskLog> list = baseMapper.selectList(new QueryWrapper<CollectionTaskLog>().eq("task_id",
                record.getTaskId()).eq("delete_flag", 0).orderByDesc("create_time")
        .last("limit 100")
        );
        for (CollectionTaskLog collectionTaskLog : list) {
            if (StringUtils.isNotEmpty(collectionTaskLog.getVersion())
                    && !collectionTaskLog.getVersion().equals(record.getVersion()) ) {
                HashMap<String, Object> version = new HashMap<>();
                version.put("id", collectionTaskLog.getId());
                version.put("version", collectionTaskLog.getVersion());
                res.add(version);
            }
        }
        return res;
    }

    @Override
    public CollectionTaskLogDetail getDetailById(Long id) {
        CollectionTaskLog record = baseMapper.selectById(id);
        if (record == null) {
            throw new RRException("任务日志不存在");
        }
        CollectionTask task = collectionTaskMapper.selectById(record.getTaskId());

        Set<Long> userIds = Sets.newHashSet();
        userIds.add(record.getTaskRunLeader());
        userIds.add(record.getUpdateUser());
        userIds.add(record.getTaskLeader());
        if(task != null)
            userIds.add(task.getTaskLeader());
        userIds.add(record.getOwnModuleLeader());
        userIds.add(record.getOwnModuleLeader());
        List<SysUserEntity> users = sysUserMapper.selectList(
                new QueryWrapper<SysUserEntity>().in("user_id", userIds));
        Map<Long, String> userMap = Maps.newHashMap();
        for (SysUserEntity user : users) {
            String name = user.getUsername();
            if (StringUtils.isNotEmpty(user.getWorkName())) {
                name = name + "(" + user.getWorkName() + ")";
            }
            userMap.put(user.getUserId(), name);
        }

        CollectionTaskLogDetail detail = new CollectionTaskLogDetail(record);
        detail.setUpdateTime(record.getRunTime());
//        List<CollectionSystemModuleEntity> moduleList = collectionSystemModuleMapper.selectList(new QueryWrapper<>());
//        String moduleName = ModuleUtils.getAllPath(moduleList, record.getOwnModule());
//        detail.setOwnModuleName(moduleName);
//        CollectionSystemModuleEntity sysEntity = collectionSystemModuleMapper
//                .selectById(record.getOwnSystem());
//        if (sysEntity != null) {
//            detail.setOwnSystemName(sysEntity.getSmName());
//        }
        List<String> categorys = collectionTaskMapper.selectCategoryIdsList(record.getTaskId().intValue(),ShiroUtils.getTenantId());
        detail.setOwnModuleName(StringUtils.join(categorys, ","));
        if(StringUtils.isNotEmpty(record.getSourceType())){
            String sourceType = ConnectTypeEnum.getTypeString(record.getSourceType());
            detail.setSourceType(sourceType);
        }

        if(task != null){
            SysRoleEntity roleEntity = sysRoleService.getById(task.getInitRole());
            if(roleEntity != null)
                detail.setRoleName(roleEntity.getRoleName());
        }
        String runLeader = userMap.get(record.getTaskRunLeader());
        String taskLeader =  task != null ? userMap.get(task.getTaskLeader()) : "";
        String updateUserName = userMap.get(record.getUpdateUser());
        detail.setUpdateUserName(updateUserName);
        detail.setTaskLeaderName(taskLeader);
        detail.setRunLeaderName(runLeader);

        CollectionRunLog logContent = collectionRunLogMapper.selectOne(
                new QueryWrapper<CollectionRunLog>().eq("log_id", id));
        if (logContent != null) {
            detail.setLogContent(logContent.getLogContent());
        }

        if (ObjectUtils.equals(record.getTaskType(), 1)) {//0 手动采集 1自动采集 2接口
            setDetail(record, detail, task);
        } else if (ObjectUtils.equals(record.getTaskType(), 2)) {
            if(StringUtils.isNotEmpty(record.getTaskConfig())){
                List<CollectionTaskLogSource> sourceList = new ArrayList<>();
                detail.setSources(sourceList);
                String[] sources = record.getTaskConfig().split(";");
                for(String source : sources){
                    String[] confs = source.split("@:");
                    ConfConnect confConnect = confConnectService.getById(Integer.valueOf(confs[0]));
                    if (confConnect != null){
                        CollectionTaskLogSource logSource = new CollectionTaskLogSource();
                        logSource.setSourceName(confConnect.getName());
                        logSource.setSourceHost(confConnect.getHost());
                        logSource.setPort(confConnect.getPort());
                        logSource.setDbName(confs[1]);
                        logSource.setCreatePer(confConnect.getCreatePer());
                        //取登录用户名
                        logSource.setCreatePerName(confConnect.getUsername());
//                        SysUserEntity user = sysUserService.getById(confConnect.getCreatePer());
//                        if(user != null){
//                        }
                        sourceList.add(logSource);
                    }
                }
            }
        }

        wrapTableLog(detail);
        return detail;
    }

    private void setDetail(CollectionTaskLog record, CollectionTaskLogDetail detail, CollectionTask task){
        ConfConnect confConnect = confConnectService.getById(record.getSourceId());
        if (confConnect != null){
            List<CollectionTaskLogSource> sources = new ArrayList<>();
            if(StringUtils.isNotEmpty(task.getDbName())){
                String[] dbNames = task.getDbName().split(",");
                for(String dbName : dbNames){
                    CollectionTaskLogSource source = new CollectionTaskLogSource();
                    source.setSourceName(confConnect.getName());
                    source.setSourceHost(confConnect.getHost());
                    source.setPort(confConnect.getPort());
                    source.setDbName(dbName);
                    source.setCreatePer(confConnect.getCreatePer());
                    source.setCreatePerName(confConnect.getUsername());
                    sources.add(source);
                }
            }
            detail.setSources(sources);
        }

        if(task != null){
            CollectionTaskScheduleConfigEntity taskScheduleConfigEntity = collectionTaskScheduleConfigService.getById(task.getId());
            if (taskScheduleConfigEntity != null){
                detail.setScheduleEnable(taskScheduleConfigEntity.getScheduleEnable());
                detail.setScheduleMode(taskScheduleConfigEntity.getScheduleMode());
                detail.setScheduleUnit(taskScheduleConfigEntity.getScheduleUnit());
                if(StringUtils.isNotEmpty(taskScheduleConfigEntity.getScheduleUnitValue())){
                    String[] split = taskScheduleConfigEntity.getScheduleUnitValue().split(" ");
                    switch (taskScheduleConfigEntity.getScheduleUnit()){
                        case 1:
                        case 2:
                            detail.setIntervalValue(Integer.parseInt(taskScheduleConfigEntity.getScheduleUnitValue()));
                            break;
                        case 3:
                            detail.setScheduleMinute(Integer.parseInt(split[0]));
                            break;
                        case 4:
                            detail.setScheduleMinute(Integer.parseInt(split[0]));
                            detail.setScheduleHour(Integer.parseInt(split[1]));
                            break;
                        case 5:
                        case 6:
                            detail.setScheduleMinute(Integer.parseInt(split[0]));
                            detail.setScheduleHour(Integer.parseInt(split[1]));
                            detail.setScheduleDay(Integer.parseInt(split[2]));
                            break;
                    }
                }
            }
        }
    }

    private void wrapTableLog(CollectionTaskLogDetail detail) {
        QueryWrapper<CollectionTableFieldLog> param = new QueryWrapper<>();
        param.eq("log_id", detail.getId());
        param.last("limit 2000");
        List<CollectionTableFieldLog> listLog = collectionTableFieldLogMapper.selectList(param);
        if (CollectionUtils.isNotEmpty(listLog)) {
            Map<Integer, List<CollectionTableFieldLog>> mapTableLogList = listLog.stream()
                    .filter(s -> s.getDataType() == 0)
                    .collect(Collectors.groupingBy(CollectionTableFieldLog::getLogType));
            Set<Integer> tableIds = listLog.stream()
                    .map(CollectionTableFieldLog::getTableId).collect(Collectors.toSet());
            Set<Integer> fieldIds = listLog.stream().filter(s -> s.getFieldId() != null)
                    .map(CollectionTableFieldLog::getFieldId).collect(Collectors.toSet());
            List<CollectionTableInfo> tableList = collectionTableInfoMapper.selectList(
                    new QueryWrapper<CollectionTableInfo>().in("id", tableIds));
            Map<Integer, CollectionTableInfo> tableListMap = tableList.stream()
                    .collect(Collectors.toMap(CollectionTableInfo::getId, a -> a, (k1, k2) -> k1));
            List<CollectionTableField> fieldList = collectionTableFieldMapper.selectList(
                    new QueryWrapper<CollectionTableField>().in("id", fieldIds));

            Map<Integer, CollectionTableField> fieldListMap = fieldList.stream()
                    .collect(Collectors.toMap(CollectionTableField::getId, a -> a, (k1, k2) -> k1));
            for (Integer type : mapTableLogList.keySet()) {
                List<CollectionTableFieldLog> tableLogList = mapTableLogList.get(type);
                if (CollectionUtils.isNotEmpty(tableLogList)) {
                    List<TableLog> tempTableList = Lists.newArrayList();
                    for (CollectionTableFieldLog collectionTableFieldLog : tableLogList) {
                        TableLog tl = new TableLog(tableListMap.get(collectionTableFieldLog.getTableId()));
                        Map<Integer, List<CollectionTableFieldLog>> mapFieldListMap =
                                listLog.stream().filter(s -> s.getDataType().intValue()== 1 && s.getFieldId() != null && s.getTableId() != null
                                        && s.getTableId().equals(collectionTableFieldLog.getTableId()))
                                        .collect(Collectors.groupingBy(CollectionTableFieldLog::getLogType));
                        for (Integer typeLog : mapFieldListMap.keySet()) {
                            List<CollectionTableFieldLog> fieldLogList = mapFieldListMap.get(typeLog);
                            if (CollectionUtils.isNotEmpty(fieldLogList)) {
                                List<FieldLog> tempLogFieldList = Lists.newArrayList();
                                for (CollectionTableFieldLog tableFieldLog : fieldLogList) {
                                    FieldLog fl = new FieldLog(fieldListMap.get(tableFieldLog.getFieldId()));
                                    fl.setChangeInfo(tableFieldLog.getChangeInfo());
                                    tempLogFieldList.add(fl);
                                }
                                if (LogTypeEnum.ADD.getValue().equals(typeLog)) {
                                    tl.setAddFieldList(tempLogFieldList);
                                }
                                if (LogTypeEnum.UPDATE.getValue().equals(typeLog)) {
                                    tl.setUpdateFieldList(tempLogFieldList);
                                }
                                if (LogTypeEnum.DELETE.getValue().equals(typeLog)) {
                                    tl.setDeleteFieldList(tempLogFieldList);
                                }
                            }
                        }
                        tempTableList.add(tl);
                    }
                    if (LogTypeEnum.ADD.getValue().equals(type)) {
                        detail.setAddTableList(tempTableList);
                    }
                    if (LogTypeEnum.DELETE.getValue().equals(type)) {
                        detail.setDeleteTableList(tempTableList);
                    }
                    if (LogTypeEnum.UPDATE.getValue().equals(type)) {
                        detail.setUpdateTableList(tempTableList);
                    }
                    if (LogTypeEnum.NONE.getValue().equals(type)) {
                        detail.setNoneTableList(tempTableList);
                    }
                }
            }
        }
    }
}
